package com.action.gulimall.product.service.impl;

import com.action.common.constant.ProductConstant;
import com.action.common.model.es.SkuEsModel;
import com.action.common.to.SkuStockTo;
import com.action.common.utils.CheckUtils;
import com.action.common.utils.R;
import com.action.gulimall.product.entity.*;
import com.action.gulimall.product.fegin.CoupenFeginService;
import com.action.gulimall.product.fegin.SearchFeginService;
import com.action.gulimall.product.fegin.WareFeginService;
import com.action.gulimall.product.service.*;
import com.action.gulimall.product.vo.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.action.gulimall.product.dao.SpuInfoDao;
import com.action.common.utils.PageUtils;
import com.action.common.utils.Query;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;
    @Autowired
    SpuImagesService spuImagesService;
    @Autowired
    AttrService attrService;
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    CoupenFeginService coupenFeginService;
    @Autowired
    WareFeginService wareFeginService;

    @Autowired
    SearchFeginService searchFeginService;

    @Autowired
    SkuInfoService skuInfoService;
    @Autowired
    SkuImagesService skuImagesService;
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );
        return new PageUtils(page);
    }

    //@GlobalTransactional(rollbackFor = Exception.class)
    @Transactional
    @Override
    public void save(SpuSaveVo spuSaveVo) {
        //1、保存spu基本信息：pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.save(spuInfoEntity);

        //保存spu的描述图片 pms_spu_info_desc
        if (!CollectionUtils.isEmpty(spuSaveVo.getDecript())) {
            SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
            spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
            spuInfoDescEntity.setDecript(String.join(",", spuSaveVo.getDecript()));
            spuInfoDescService.save(spuInfoDescEntity);
        }

        //保存spu的图片集   pms_spu_images
        if (!CollectionUtils.isEmpty(spuSaveVo.getImages())) {
            List<SpuImagesEntity> collect = spuSaveVo.getImages().stream().map(image -> {
                SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
                spuImagesEntity.setSpuId(spuInfoEntity.getId());
                spuImagesEntity.setImgUrl(image);
                return spuImagesEntity;
            }).collect(Collectors.toList());
            spuImagesService.saveBatch(collect);
        }

        //保存spu的规格参数 pms_product_attr_value
        if (!CollectionUtils.isEmpty(spuSaveVo.getBaseAttrs())) {
            List<ProductAttrValueEntity> productAttrValueEntities = spuSaveVo.getBaseAttrs().stream().map(attr -> {
                ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
                productAttrValueEntity.setSpuId(spuInfoEntity.getId());
                //查询属性的名称
                AttrEntity attrEntity = attrService.getById(attr.getAttrId());
                productAttrValueEntity.setAttrId(attrEntity.getAttrId());
                productAttrValueEntity.setAttrName(attrEntity.getAttrName());
                productAttrValueEntity.setAttrValue(attr.getAttrValues());
                productAttrValueEntity.setQuickShow(attr.getShowDesc());
                return productAttrValueEntity;
            }).collect(Collectors.toList());
            productAttrValueService.saveBatch(productAttrValueEntities);
        }
        //保存spu的积分信息 gulimall_sms-> sms_spu_bounds
        if (spuSaveVo.getBounds() != null) {
            BoundInfoVo boundInfoVo = new BoundInfoVo();
            BeanUtils.copyProperties(spuSaveVo.getBounds(), boundInfoVo);
            boundInfoVo.setSpuId(spuInfoEntity.getId());

            //调用远程积分服务
            R r = coupenFeginService.saveSpuBounds(boundInfoVo);
            if (r.getCode() != 0) {
                log.error("调用远程积分服务保存积分失败,失败原因:" + JSON.toJSONString(r));
            }
        }

        //保存当前spu对应的sku信息

        //sku的图片信息   pms_sku_images
        //sku的销售属性值 pms_sku_sale_attr_value
        //sku的优惠折扣，满减信息 会员价格 积分
        //gulimall_sms->sms_sku_lader\sms_sku_full_reduction\sms_member_price

        //sku的基本信息   pms_sku_info
        List<Skus> skus = spuSaveVo.getSkus();
        if (!CollectionUtils.isEmpty(skus)) {
            skus.forEach(item -> {
                String defaultImg = "";
                for (Images image : item.getImages()) {
                    if (image.getDefaultImg() == 1) {
                        defaultImg = image.getImgUrl();
                    }
                }
                SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                BeanUtils.copyProperties(item, skuInfoEntity);
                skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
                skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
                skuInfoEntity.setSaleCount(0L);
                skuInfoEntity.setSpuId(spuInfoEntity.getId());
                skuInfoEntity.setSkuDefaultImg(defaultImg);
                skuInfoService.save(skuInfoEntity);

                Long skuId = skuInfoEntity.getSkuId();
                //sku的图片信息：pms_sku_images
                if (!CollectionUtils.isEmpty(item.getImages())) {
                    List<SkuImagesEntity> imagesEntities = item.getImages().stream().map(img -> {
                        SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                        skuImagesEntity.setSkuId(skuId);
                        skuImagesEntity.setImgUrl(img.getImgUrl());
                        skuImagesEntity.setDefaultImg(img.getDefaultImg());
                        return skuImagesEntity;
                    }).filter(entity -> {
                        //返回true就是需要，false就是剔除
                        return !StringUtils.isEmpty(entity.getImgUrl());
                    }).collect(Collectors.toList());
                    skuImagesService.saveBatch(imagesEntities);
                }

                //sku的销售属性：pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                if (!CollectionUtils.isEmpty(attrs)) {
                    List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attrs.stream().map(a -> {
                        SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                        BeanUtils.copyProperties(a, skuSaleAttrValueEntity);
                        skuSaleAttrValueEntity.setSkuId(skuId);
                        return skuSaleAttrValueEntity;
                    }).collect(Collectors.toList());
                    skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);
                }

                //sku的优惠、满减等信息：gulimall_sms--->sms_sku_ladder、sms_sku_full_reduction、sms_member_price
                //远程调用积分服务
                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtils.copyProperties(item, skuReductionTo);
                skuReductionTo.setSkuId(skuId);
                if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(BigDecimal.ZERO) == 1) {
                    R r1 = coupenFeginService.saveSkuReduction(skuReductionTo);
                    if (r1.getCode() != 0) {
                        log.error("远程保存sku积分信息失败");
                    }
                }
            });
        }
    }

    @Override
    public PageUtils searchPage(Map<String, Object> params) {
        String key = (String) params.get("key");
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<SpuInfoEntity>();
        if (!StringUtils.isEmpty(key)) {
            queryWrapper.and(qw -> {
                if (CheckUtils.isInteger(key)) {
                    qw.eq("id", Long.valueOf(key)).or().like("spu_name", key);
                } else {
                    qw.like("spu_name", key);
                }
            });
        }
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            queryWrapper.eq("publish_status", Integer.valueOf(status));
        }
        String catelogId = (String) params.get("catelogId");
        if (!StringUtils.isEmpty(catelogId) && Long.valueOf(catelogId) > 0) {
            queryWrapper.eq("catalog_id", Long.valueOf(catelogId));
        }
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId) && Long.valueOf(brandId) > 0) {
            queryWrapper.eq("brand_id", Long.valueOf(brandId));
        }
        IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params), queryWrapper);

        return new PageUtils(page);
    }

    @Override
    public void up(Long spuId) {
        //查询spu信息，sku信息
        //1.spu对应的sku信息
        List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkuInfosBySpuId(spuId);
        List<Long> skuIds = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        //2.spu的可以搜索的属性  pms_attr(search_type=1)  pms_product_attr_value 取 交集
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.getAttrsBySpuId(spuId);
        List<Long> pAttrIds = productAttrValueEntities.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
        //查询池可以搜索的属性集合
        List<AttrEntity> attrEntities = attrService.getCanSearchAttrs(pAttrIds);
        Set<Long> canSearchAttrIdSet = attrEntities.stream().map(AttrEntity::getAttrId).collect(Collectors.toSet());
        //spuId对应的可以搜索的属性集合
        List<SkuEsModel.Attr> attrList = productAttrValueEntities.stream()
                .filter(productAttrValueEntity -> canSearchAttrIdSet.contains(productAttrValueEntity.getAttrId()))
                .map(productAttrValueEntity -> {
                    SkuEsModel.Attr attr = new SkuEsModel.Attr();
                    BeanUtils.copyProperties(productAttrValueEntity, attr);
                    return attr;
                }).collect(Collectors.toList());
        //3.远程调用检测是否有库存，批量查询一个产品的多个skuId的库存
        Map<Long, Boolean> hasStockMap = null;
        try {
            log.trace("---spuId=" + spuId + ",远程调用库存服务查询库存---");
            R r = wareFeginService.skusHasStocks(skuIds);
            Optional<List<SkuStockTo>> rData = r.getData(new TypeReference<List<SkuStockTo>>() {
            });
            if (rData.isPresent()) {
                hasStockMap = rData.get().stream().collect(Collectors.toMap(SkuStockTo::getSkuId, SkuStockTo::getHasStock));
            } else {
                for (Long skuId : skuIds) {
                    hasStockMap.put(skuId, Boolean.FALSE);
                }
            }
        } catch (Exception e) {
            log.error("远程查询skuIds{" + skuIds.toString() + "}库存出现异常", e);
            hasStockMap = new HashMap<>();
            for (Long skuId : skuIds) {
                hasStockMap.put(skuId, Boolean.FALSE);
            }
        }
        //4.组装List<SkuModelVo>
        Map<Long, Boolean> finalHasStockMap = hasStockMap;
        List<SkuEsModel> skuEsModels = skuInfoEntities.stream().map(skuInfoEntity -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfoEntity, skuEsModel);
            skuEsModel.setSkuImg(skuInfoEntity.getSkuDefaultImg());
            //品牌
            BrandEntity brandEntity = brandService.getById(skuInfoEntity.getBrandId());
            skuEsModel.setBrandId(skuInfoEntity.getBrandId());
            skuEsModel.setBrandName(brandEntity.getName());
            skuEsModel.setBrandImg(brandEntity.getLogo());
            //分类
            CategoryEntity categoryEntity = categoryService.getById(skuInfoEntity.getCatalogId());
            skuEsModel.setCatalogId(skuInfoEntity.getCatalogId());
            skuEsModel.setCatalogName(categoryEntity.getName());
            //热度
            skuEsModel.setHotScore(0L);
            //价格
            skuEsModel.setSkuPrice(skuInfoEntity.getPrice());
            skuEsModel.setHasStock(finalHasStockMap.get(skuInfoEntity.getSkuId()));
            //可搜索的参数规格属性
            skuEsModel.setAttrs(attrList);
            return skuEsModel;
        }).collect(Collectors.toList());
        //5.远程调用搜索服务，将skuModel保存到elasticsearch中
        R r = searchFeginService.saveSkuModelsToEs(skuEsModels);
        if (r.getCode() != 0) {
            log.error("spuId=" + spuId + ",远程调用搜索服务保存skuModels信息出现异常," + r.getMsg());
        } else {
            log.trace("spuId=" + spuId + ",远程调用搜索服务保存成功");
        }
        // 6.修改当前spu的状态
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        spuInfoEntity.setId(spuId);
        spuInfoEntity.setPublishStatus(ProductConstant.ProductStatusEnum.SPU_UP.getCode());
        spuInfoEntity.setUpdateTime(new Date());
        baseMapper.updateById(spuInfoEntity);
        log.trace("spuId=" + spuId + ",上架成功");
    }

    @Override
    public SpuInfoEntity getSpuInfoBySkuId(Long skuId) {
        //先查询sku表里的数据
        SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);

        //获得spuId
        Long spuId = skuInfoEntity.getSpuId();

        //再通过spuId查询spuInfo信息表里的数据
        SpuInfoEntity spuInfoEntity = this.baseMapper.selectById(spuId);

        //查询品牌表的数据获取品牌名
        BrandEntity brandEntity = brandService.getById(spuInfoEntity.getBrandId());
        spuInfoEntity.setBrandName(brandEntity.getName());

        return spuInfoEntity;
    }
}